package net.esj.basic.utils.hibe;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import net.esj.basic.dao.hibernate.HibernateQueryBuilder.CriEntity;
import net.esj.basic.utils.Assert;
import net.esj.basic.utils.StringUtils;
import net.esj.basic.utils.Validators;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

public class AndCriteria implements HiCriteria, Cloneable {

	private Criterion curCriterion = null;
	
	private Set<String> subKeys = new HashSet<String>();
	
	private AndCriteria() {
		super();
	}

	/**
	 * 判断是否在给定的区间里
	 * @param propertyName
	 * @param lo
	 * @param hi
	 */
	@Override
	public AndCriteria between(String propertyName, Object lo, Object hi) {
		Assert.notNull(lo, "传值不能为空！");
		Assert.notNull(hi, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.between(propertyName, lo, hi);
		}else{
			curCriterion = Restrictions.and(Restrictions.between(propertyName, lo, hi), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否相等
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria eq(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.eq(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.eq(propertyName, value), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否大于等于
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria ge(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.ge(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.ge(propertyName, value), curCriterion);
		}
		return this;
	}

	@Override
	public HiCriteria gt(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.gt(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.gt(propertyName, value), curCriterion);
		}
		return this;
	}

	/**
	 * 根据matchMode判断是否匹配
	 * @param propertyName
	 * @param value
	 * @param matchMode
	 */
	@Override
	public HiCriteria ilike(String propertyName, String value,
			MatchMode matchMode) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.ilike(propertyName, value,matchMode);
		}else{
			curCriterion = Restrictions.and(Restrictions.ilike(propertyName, value,matchMode), curCriterion);
		}
		return this;
	}

	/**
	 * 忽略大小写的like搜索
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria ilike(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.ilike(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.ilike(propertyName, value), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否在给定的数组里
	 * @param propertyName
	 * @param values
	 */
	@Override
	public HiCriteria in(String propertyName, Object[] values) {
		Assert.notNull(values, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.in(propertyName, values);
		}else{
			curCriterion = Restrictions.and(Restrictions.in(propertyName, values), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否在给定的集合里
	 * @param propertyName
	 * @param values
	 */
	@Override
	public HiCriteria in(String propertyName, Collection values) {
		Assert.notNull(values, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.in(propertyName, values);
		}else{
			curCriterion = Restrictions.and(Restrictions.in(propertyName, values), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否不等于
	 * @param propertyName
	 */
	@Override
	public HiCriteria isNotNull(String propertyName) {
		if(curCriterion==null){
			curCriterion =Restrictions.isNotNull(propertyName);
		}else{
			curCriterion = Restrictions.and(Restrictions.isNotEmpty(propertyName), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否为空
	 * @param propertyName
	 */
	@Override
	public HiCriteria isNull(String propertyName) {
		if(curCriterion==null){
			curCriterion =Restrictions.isNull(propertyName);
		}else{
			curCriterion = Restrictions.and(Restrictions.isNull(propertyName), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否小于等于
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria le(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.le(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.le(propertyName, value), curCriterion);
		}
		return this;
	}

	@Override
	public HiCriteria like(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.like(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.like(propertyName, value), curCriterion);
		}
		return this;
	}

	/**
	 * 根据matchMode判断是否匹配
	 * @param propertyName
	 * @param value
	 * @param matchMode
	 */
	@Override
	public HiCriteria like(String propertyName, String value,
			MatchMode matchMode) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.like(propertyName, value,matchMode);
		}else{
			curCriterion = Restrictions.and(Restrictions.like(propertyName, value,matchMode), curCriterion);
		}
		return this;
	}

	/**
	 * 判断是否小于
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria lt(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.lt(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.lt(propertyName, value), curCriterion);
		}
		return this;
	}

	/**
	 * 不等于.
	 * @param propertyName
	 * @param value
	 */
	@Override
	public HiCriteria notEq(String propertyName, Object value) {
		Assert.notNull(value, "传值不能为空！");
		if(curCriterion==null){
			curCriterion =Restrictions.ne(propertyName, value);
		}else{
			curCriterion = Restrictions.and(Restrictions.ne(propertyName, value), curCriterion);
		}
		return this;
	}

	public static HiCriteria createMe(){
		return new AndCriteria();
	}

	@Override
	public Criterion getCriterion() {
		return curCriterion;
	}

	@Override
	public HiCriteria add(HiCriteria lhs,HiCriteria rhs){
		curCriterion = Restrictions.and(lhs.getCriterion(), rhs.getCriterion());
		return this;
	}

	private void checkPropertyName(String name){
		if(name.indexOf("\\.")>0){
			subKeys.add(name);
		}
	}

}
